package com.lp.batch;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.oxm.XmlMappingException;

import com.lp.batch.domain.Node;
import com.lp.batch.domain.Taxonomies;
import com.lp.batch.service.TaxonomyService;
import com.lp.batch.service.TemplateService;
import com.lp.batch.service.impl.VelocityServiceImpl;

/**
 * This class will print a number of HTML files containing a number of destinations.
 * This class can be executed from the command line with the following options:
 * -o followed by a full path to a folder where you would like to write an HTML file for each destination 
 * -d followed by the name of the destination xml file
 * -t followed by the name of the taxonomy xml file
 * -s followed by the name of a css file that can be applied to the html files
 * 
 * Example: 
 * java Main -o c:\out -d c:\destinations.xml -t c:\taxonomy.xml -s c:\my.css
 * 
 * @author Zainul Franciscus
 * 
 */
public class Main {

	/**
	 * Use this option to specify a folder to write the html file
	 */
	private static final String OUPUT_OPTION = "o";

	/**
	 * Use this option to specify the location of the destination.xml
	 */
	private static final String DESTINATION_OPTION = "d";

	/**
	 * Use this option to specify the location of the taxonomy.xml
	 */
	private static final String TAXONOMY_OPTION = "t";
	
	/**
	 * An optional option that can be used to specify a stylesheet
	 */
	private static final String STYLESHEET_OPTION = "s";

	public static void main(String[] userInputs) throws MarshalException, ValidationException, IOException, MappingException, XmlMappingException, ParseException {

		System.out.println("This application started at : " + new Date());

		Main main = new Main();

		TaxonomyService taxonomyService = main.taxonomyService();
		TemplateService velocityService = main.templateService();

		Taxonomies taxonomies = taxonomyService.selectTaxonomies(main.getTaxonomyFileLocation(userInputs));

		List<Node> allDestinations = taxonomies.getAllDestinations();

		String destinationFile = main.getDestinationFileLocation(userInputs);
		String outputFolder = main.getOutputLocation(userInputs);

		for (Node destination : allDestinations) {
			String description = taxonomyService.selectIntroAndHistory(destination.getAtlasNodeId(), destinationFile);
			destination.setDescription(description);
			velocityService.createAPageFromTemplate(outputFolder, destination);
		}

		String cssLocation = main.getStylesheet(userInputs);
		File stylesheet = new File(cssLocation);
		velocityService.createStyleSheet(outputFolder, stylesheet);

		System.out.println("The application completed at: " + new Date());

	}

	/**
	 * Used to load service beans in this applications
	 */
	GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();

	/**
	 * Contains command line options for this application.
	 */
	private Options cliOptions = new Options();

	public Main() {
		ctx.load("classpath:META-INF/spring/app-context.xml");
		ctx.refresh();

		cliOptions.addOption(TAXONOMY_OPTION, true, "a mandatory option for user to specify a taxonomy file name");
		cliOptions.addOption(DESTINATION_OPTION, true, "a mandatory option for user to specify a destination file name");
		cliOptions.addOption(OUPUT_OPTION, true, "a mandatory option for user to specify an output folder");
		cliOptions.addOption(STYLESHEET_OPTION,true,"user can specify a style sheet that can be applied to the html file");
	}

	/**
	 * @return a TaxonomyService object that can be used to load destinations
	 */
	private TaxonomyService taxonomyService() {
		return (TaxonomyService) ctx.getBean("taxonomyService", TaxonomyService.class);
	}

	/**
	 * @return a TemplateService that can be use to write an HTML file which has
	 *         destinations.
	 */
	private TemplateService templateService() {
		return (TemplateService) ctx.getBean("velocityService", VelocityServiceImpl.class);

	}

	/**
	 * @param userInputs
	 * @return a location of a style sheet from the command line
	 * @throws ParseException
	 */
	private String getStylesheet(String[] userInputs ) throws ParseException{
		return selectThisOptionFromUserInputs(STYLESHEET_OPTION, userInputs);
	}
	/**
	 * @param userInputs
	 * @return a location of a taxonomy.xml file from the command line
	 * @throws ParseException
	 */
	private String getTaxonomyFileLocation(String[] userInputs) throws ParseException {

		return selectThisOptionFromUserInputs(TAXONOMY_OPTION, userInputs);
	}

	/**
	 * @param userInputs
	 * @return a location of the destination.xml file from the command line
	 * @throws ParseException
	 */
	private String getDestinationFileLocation(String[] userInputs) throws ParseException {
		return selectThisOptionFromUserInputs(DESTINATION_OPTION, userInputs);
	}

	/**
	 * @param userInputs
	 * @return a location of a folder where the HTML pages should be written.
	 * @throws ParseException
	 */
	private String getOutputLocation(String[] userInputs) throws ParseException {
		return selectThisOptionFromUserInputs(OUPUT_OPTION, userInputs);
	}

	/**
	 * @param option that a user can specify in the command line
	 * @param userInputs is what a user has written in the command line
	 * @return what user has written in the command line for the specified option
	 * @throws ParseException
	 */
	private String selectThisOptionFromUserInputs(String option, String[] userInputs) throws ParseException {
		BasicParser parser = new BasicParser();
		CommandLine cl = parser.parse(cliOptions, userInputs);
		return cl.getOptionValue(option);
	}

}
